package com.sdk.auth.utils;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @author wst
 * @date 2023/7/4
 * 反射工具类
 */
@Slf4j
public class ReflectionUtil {

    /**
     * 递归查找目标字段值
     * @param fieldName 目标字段名
     * @param obj   待查找对象
     * @param level 递归层级，一般不要超过 10 层
     * @return 目标字段值
     */
    public static Object recursionObj(String fieldName, Object obj, int level) {
        log.debug("recursionObj {}-{}-{}", fieldName, level, obj);
        if (StrUtil.isBlank(fieldName) || obj == null || isPrimitive(obj.getClass()) || level <= 0) {
            return null;
        }
        try {
            if (obj.getClass().isArray()) {
                // 数组
                for (Object o : (Object[]) obj) {
                    return recursionObj(fieldName, o, --level);
                }
            } else if (Collection.class.isAssignableFrom(obj.getClass())) {
                for (Object o : ((Collection) obj)) {
                    return recursionObj(fieldName, o, --level);
                }
            } else {
                return lookupField(fieldName, obj, level);
            }
        } catch (Exception e) {
            log.error("递归遍历数据异常：{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 查找目标字段值
     * @param fieldName 目标字段名
     * @param obj   待查找对象
     * @param level 递归层级，一般不要超过 10 层
     * @return 目标字段值
     */
    private static Object lookupField(String fieldName, Object obj, int level) {
        Object result = null;
        if (Map.class.isAssignableFrom(obj.getClass())) {
            for (Map.Entry entry : ((Map<?, ?>) obj).entrySet()) {
                try {
                    Object fieldValue = entry.getValue();
                    log.debug("entry: {}-{}", entry.getKey(), fieldValue);
                    if (fieldName.equals(entry.getKey())) {
                        return fieldValue;
                    } else if (fieldValue != null && !isPrimitive(fieldValue.getClass())) {
                        result = recursionObj(fieldName, fieldValue, --level);
                    }
                    if (result != null) {
                        return result;
                    }
                } catch (Exception e) {
                    log.error("查找目标字段异常：{}", e.getMessage(), e);
                }
            }
        } else {
            for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
                for (Field field : Class.class.getDeclaredFields()) {
                    try {
                        ReflectionUtils.makeAccessible(field);
                        Object fieldValue = ReflectionUtils.getField(field, obj);
                        log.debug("field: {}-{}", field.getName(), fieldValue);
                        if (fieldName.equals(field.getName())) {
                            return fieldValue;
                        } else if (fieldValue != null && !isPrimitive(fieldValue.getClass())) {
                            result = recursionObj(fieldName, fieldValue, --level);
                        }
                        if (result != null) {
                            return result;
                        }
                    } catch (Exception e) {
                        log.error("查找目标字段异常：{}", e.getMessage(), e);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 基本数据类型和String类型判断
     * @param clz 对象类型
     * @return 是否基类
     */
    private static boolean isPrimitive(Class<?> clz) {
        try {
            if (String.class.isAssignableFrom(clz) || Enum.class.isAssignableFrom(clz) || clz.isPrimitive()) {
                return true;
            } else {
                return ((Class) clz.getField("TYPE").get(null)).isPrimitive();
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 递归处理字段数据
     * @param obj   待查找对象
     * @param level 递归层级，一般不要超过 10 层
     */
    public static void recursionMethod(Object obj, int level, Consumer<Map> func) {
        log.debug("recursionMethod {}-{}", level, obj);
        if (obj == null || isPrimitive(obj.getClass()) || level <= 0) {
            return;
        }
        try {
            if (obj.getClass().isArray()) {
                // 数组
                for (Object object : (Object[]) obj) {
                    recursionMethod(object, level--, func);
                }
            } else if (Collection.class.isAssignableFrom(obj.getClass())) {
                for (Object object : ((Collection) obj)) {
                    recursionMethod(object, level--, func);
                }
            } else if (Map.class.isAssignableFrom(obj.getClass())) {
                for (Object o : ((Map) obj).values()) {
                    recursionMethod(o, level--, func);
                }
            } else {
                Map<String, Object> param = new HashMap<>(2);
                param.put("obj", obj);
                param.put("level", --level);
                func.accept(param);
            }
        } catch (Exception e) {
            log.error("递归遍历数据异常：{}", e.getMessage(), e);
        }
    }
}
